#pragma once
#include <map>
#include <vector>
#include <string>
#include <stdexcept>
#include "lexical_cast.h"

namespace krryn{
namespace gui{
class property_not_found : std::runtime_error{
public:
	property_not_found(const std::string &a_Property) : std::runtime_error(a_Property) {}
};

class properties{
public:
	void insert(const std::string &a_Key, const std::string &a_Value){
		m_Settings.insert(std::make_pair(a_Key, a_Value));
	}

	bool has(const std::string &a_Name) const{
		return m_Settings.find(a_Name) != m_Settings.end();
	}

	template<typename _Type>
	_Type get(const std::string &a_Name) const {
		props_t::const_iterator l_Iter = m_Settings.find(a_Name);
		if(l_Iter == m_Settings.end())
			throw property_not_found(a_Name);

		return krryn::core::lexical_cast<_Type>(l_Iter->second);
	}

	template<typename _Type>
	_Type get(const std::string &a_Name, _Type a_DefaultValue) const{
		try{
			return get<_Type>(a_Name);
		}catch(property_not_found &){
			return a_DefaultValue;
		}
	}

	template<typename _Type>
	const std::vector<_Type>& get_list(const std::string &a_Name) const {
		std::vector<_Type> l_Array;

		props_t::const_iterator l_Iter = m_Settings.find(a_Name);

		if(l_Iter == m_Settings.end())
			throw property_not_found(a_Name);

		props_t::const_iterator l_End = m_Settings.upper_bound(a_Name);

		for(; l_Iter != l_End; ++l_Iter){
			l_Array.push_back(krryn::core::lexical_cast<_Type>(l_Iter->second));
		}

		return l_Array;
	}
private:
	typedef std::multimap<std::string, std::string> props_t;
	props_t m_Settings;
};

}
}